package service

import (
	"encoding/binary"
	"errors"
	"io"
	"log"

	"github.com/panjf2000/gnet/v2"
)

func Decode(c gnet.Conn) (*Message, error) {
	b, err := c.Next(1)
	if err != nil || len(b) < 1 {
		return nil, err
	}
	mt := b[0]
	msg := &Message{}
	msg.Type = MessageType(mt)

	l, err := decodeLength(c)
	if err != nil {
		return nil, err
	}

	if c.InboundBuffered() < int(l) {
		return nil, ErrInvalidLength
	}
	n, err := io.CopyN(&msg.buffer, c, int64(l))
	if err != nil || n != int64(l) {
		return nil, errors.New("read payload error")
	}
	return msg, nil
}

func decodeLength(c gnet.Conn) (uint64, error) {

	var multiplier uint64 = 1
	var value uint64
	for i := 0; i < 4; i++ {
		b, err := c.Next(1)
		if err != nil {
			return 0, err
		}
		digit := uint64(b[0])
		value += (digit & 127) * multiplier
		multiplier *= 128
		if digit&128 == 0 {
			break
		}
	}
	if value > 268435455 {
		return 0, errors.New("length too long")
	}
	return value, nil
}

func encodeLength(x uint64) []byte {
	var buff []byte
	for x > 0 {
		digit := x % 128
		x = x / 128
		if x > 0 {
			digit = digit | 128
		}
		buff = append(buff, byte(digit))
	}
	return buff
}

func getLength(c gnet.Conn) (uint64, error) {
	var buff = make([]byte, 8)
	for i := 0; i < 4; i++ {
		b, err := c.Next(1)
		if err != nil || len(b) < 1 {
			return 0, err
		}
		if b[0] < 0x80 {
			buff[7-i] = b[0]
			break
		}
		buff[7-i] = b[0]
	}

	l := binary.BigEndian.Uint64(buff)
	// if n == 0 {
	// 	return 0, errors.New("read length error")
	// }
	log.Println("read length:", buff, l)
	return l, nil
}
